using System;
using System.Threading.Tasks;
using UnityEngine;
using WolfCarol.AvgToolkit.Command;
using WolfCarol.AvgToolkit.Tween;
using WolfCarol.AvgToolkit.Save;

namespace WolfCarol.AvgToolkit.Examples
{
    [Serializable]
    public class AudioData
    {
        public string Path;

        public bool IsLoop;

        public float Second;

        public float Volume;

        public bool IsPlaying;

        public AudioData()
        {
            Path = string.Empty;
            IsLoop = false;
            Second = 0;
            Volume = 0;
            IsPlaying = false;
        }
    }

    [RequireComponent(typeof(AudioSource))]
    public class StageAudio : MonoBehaviour, ISavable<AudioData>
    {
        private AudioSource m_source;

        private float m_volume;

        private const float FadeTime = 0.25f;

        private void Awake()
        {
            m_source = GetComponent<AudioSource>();
            m_source.playOnAwake = false;
        }

        [Command("play", ExecutionOrders.Parallel)]
        public async Task PlayAudio(string name, float second = 0f, bool isLoop = false)
        {
            AudioClip clip = Resources.Load<AudioClip>(name);
            if (clip == null)
            {
                throw new ArgumentException($"Could not find clip: {name}.");
            }
            m_source.clip = clip;
            m_source.loop = isLoop;
            m_source.time = second;
            m_source.Play();
            m_volume = 1f;
            await m_source.DoVolume(m_volume, FadeTime, Ease.InSine);
        }

        [Command("resume", ExecutionOrders.Parallel)]
        public async Task ResumeAudio()
        {
            m_source.Play();
            m_volume = 1f;
            await m_source.DoVolume(m_volume, FadeTime, Ease.InSine);
        }

        [Command("pause", ExecutionOrders.Parallel)]
        public async Task PauseAudio()
        {
            m_volume = 0f;
            await m_source.DoVolume(m_volume, FadeTime, Ease.OutSine);
            m_source.Pause();
        }

        public void Clear()
        {
            m_source.Stop();
            m_source.clip = null;
            m_source.loop = false;
            m_volume = 0f;
            m_source.volume = m_volume;
        }

        public AudioData Save()
        {
            return new AudioData()
            {
                Path = m_source.clip ? m_source.clip.name : string.Empty,
                IsLoop = m_source.loop,
                Second = m_source.clip ? m_source.time : 0f,
                Volume = m_volume,
                IsPlaying = m_source.isPlaying
            };
        }

        public void Load(AudioData obj)
        {
            m_source.clip = Resources.Load<AudioClip>(obj.Path);
            m_source.loop = obj.IsLoop;
            if (m_source.clip)
            {
                m_source.time = obj.Second;
            }
            m_volume = obj.Volume;
            m_source.volume = m_volume;
            if (obj.IsPlaying)
            {
                m_source.Play();
            }
        }
    }
}
